document.write("<script type='text/javascript' src='" + PSI.Const.BASE_URL + "Public/Sheetjs/helper.js'></script>");
document.write("<script type='text/javascript' src='" + PSI.Const.BASE_URL + "Public/Sheetjs/dist/xlsx.core.min.js'></script>");

var showInfo = function (info, func) {
    Ext.Msg.show({
        title: "提示",
        msg: info,
        icon: Ext.Msg.INFO,
        buttons: Ext.Msg.OK,
        minHeight: 120,
        modal: true,
        fn: function () {
            if (func) {
                func();
            }
        }
    });
}

var ajax = function (r) {
    if (!r.method) {
        r.method = "POST";
    }
    Ext.Ajax.request(r);
};

/**
 *
 * @param fileName 文件名
 * @param url 获取数据的url
 * @param queryParams 请求参数
 * @param pageSize 每次请求多少条数据
 * @param mergeHeader 合并行（置于首行）
 * @param headerArr 标题行
 * @param fieldArr 数据列字段列表
 * @param getItemRowCallBack 数据行获取回调方法
 * @param getItemRowsCallBack 数据行获取回调方法 一行被拆成多行导出
 * @param method 获取数据的http method
 * @param totalFieldName 接口返回数据的总数字段名
 * @param dataFieldName 接口返回数据的数据字段名
 * @param requestHeaders 请求接口的headers
 * @param sheetConfig 表格的配置（宽度等配置）
 * @param totalLimit 导出总数限制
 * @param errorMsgHandleCallBack 请求完所有数据的回调 用于暂停下载 抛出错误
 */
function exportList({ fileName, url, queryParams = {}, pageSize = 100, headerArr, mergeHeader = null, fieldArr, getItemRowCallBack = null, getItemRowsCallBack = null, method = 'POST', totalFieldName = 'totalCount', dataFieldName = 'dataList', requestHeaders = {}, sheetConfig = null, totalLimit = null, errorMsgHandleCallBack = null }) {
    var body = Ext.getBody();
    //第一步 先去请求列表总数量
    var queryCount = function () {
        queryParams.start = 0;
        queryParams.limit = 1;
        return new Promise(function (resolve, reject) {
            var r = {
                url: url,
                method: method,
                params: queryParams,
                headers: requestHeaders,
                callback: function (options, success, response) {
                    if (success) {
                        var data = Ext.JSON.decode(response.responseText);
                        // 兼容yii返回的数据结构
                        if (typeof data['data'] != 'undefined') {
                            data = data['data'];
                        }
                        if (data) {
                            total = data[totalFieldName];
                            resolve(total);
                        } else {
                            reject('网络错误');
                        }
                    } else {
                        reject('网络错误');
                    }
                }
            };
            ajax(r);
        })
    }

    body.mask("准备导出数据，请不要关闭页面，否则将不能导出excel");

    //查询出来总数是多少后 分批次下载
    queryCount().then(function (total) {
        if (totalLimit !== null && total > totalLimit) {
            showInfo('单次最多下载' + totalLimit + '条记录，' + '本次下载总数：' + total + '，请调整查询条件后重试');
            body.unmask();
        } else {
            if (total <= 0) {
                showInfo('没有数据可以下载');
                body.unmask();
            } else {
                generateExcel(total);
            }
        }
    }, function (errInfo) {
        showInfo(errInfo);
    }).catch(function (err) {
        console.log(err);
        showInfo('下载数据失败，请刷新页面后重试');
    });

    var generateExcel = function (total) {
        let aoa = [];
        let pages = Math.ceil(total / pageSize);
        let currentQueryPage = 1;

        let batchQueryDataPromise = function () {
            return new Promise(function (resolve, reject) {
                let batchQueryPromiseArr = [];
                for (let i = 0; i < pages; i++) {
                    currentQueryPage = i + 1
                    let p = new Promise(function (resolve, reject) {
                        let progress = (currentQueryPage / pages).toFixed(2) * 100;
                        body.mask("正在下载数据:" + progress + '%，请不要关闭页面，否则将不能导出excel');
                        queryParams.start = (currentQueryPage - 1) * pageSize;
                        queryParams.limit = pageSize;
                        let r = {
                            url: url,
                            method: method,
                            headers: requestHeaders,
                            params: queryParams,
                            callback: function (options, success, response) {
                                if (success) {
                                    var data = Ext.JSON.decode(response.responseText);
                                    // 兼容yii返回的数据结构
                                    if (typeof data['data'] != 'undefined') {
                                        data = data['data'];
                                    }
                                    if (data) {
                                        let dataList = data[dataFieldName];
                                        resolve(dataList);
                                    } else {
                                        reject('网络错误');
                                    }
                                } else {
                                    reject('网络错误');
                                }
                            }
                        };
                        ajax(r);
                    })
                    batchQueryPromiseArr.push(p);
                }

                Promise.all(batchQueryPromiseArr).then(function (values) {
                    for (var i = 0; i < values.length; i++) {
                        let pageData = values[i];
                        for (var j = 0; j < pageData.length; j++) {
                            let item = pageData[j];
                            let row = [];
                            if (getItemRowsCallBack) {
                                row = getItemRowsCallBack(item, sheetConfig);
                            } else if (getItemRowCallBack) {
                                row = getItemRowCallBack(item, sheetConfig, fieldArr);
                            } else {
                                for (var field = 0; field < fieldArr.length; field++) {
                                    row.push(item[fieldArr[field]])
                                }
                            }
                            if (getItemRowsCallBack) {//如果一行被拆成多行
                                aoa = aoa.concat(row);
                            } else {
                                aoa.push(row);
                            }
                        }
                    }
                    resolve(aoa);
                }, function (errInfo) {
                    reject(errInfo);
                }).catch(function (err) {
                    console.log(err);
                    reject('下载数据失败，请刷新页面后重试');
                })
            });
        }
        //批量去请求数据
        let batchQueryData = function () {
            batchQueryDataPromise().then(function (aoa) {
                if (currentQueryPage < pages) {
                    batchQueryData();
                } else {
                    if (errorMsgHandleCallBack) {
                        let isContinue = errorMsgHandleCallBack();
                        if (!isContinue) {
                            body.unmask();
                            return;
                        }
                    }
                    aoa.unshift(headerArr);
                    if (mergeHeader) {
                        aoa.unshift(mergeHeader);
                    }
                    var sheet = XLSX.utils.aoa_to_sheet(aoa);
                    body.mask("正在生成excel，请不要关闭页面，否则将不能导出excel");
                    if (sheetConfig) {
                        for (key in sheetConfig) {
                            sheet[key] = sheetConfig[key];
                        }
                    }
                    openDownloadDialog(sheet2blob(sheet), fileName + '.xlsx');
                    body.unmask();
                }
            }, function (errInfo) {
                showInfo(errInfo);
                body.unmask();
            }).catch(function (err) {
                console.log(err);
                showInfo('下载数据失败，请刷新页面后重试');
                body.unmask();
            })
        }
        batchQueryData();
    }
}

/**
 * 导出方法 针对 yii接口
 * @param {String} fileName 文件名
 * @param {String} url 请求的地址
 * @param {String} method 请求的方法
 * @param {Object} params 查询条件
 * @param {Object} headers 请求头
 * @param {Number} limit 每页查询多少条
 * @param {Number} total 要导出多少条
 * @param {ColumnItem[]} columns 表格列的配置
 * @param {Function} getRowsCallBack 处理数据的函数
 * @param {String} totalField 接口返回数据的数据字段名
 * @param {String} dataField 接口返回数据的总数字段名
 * @param {Object} sheetConfig 表格的配置（宽度等配置）
 * @param {Function} callback 生成后调用的函数
 * 
 * @typedef ColumnItem 表格列选项
 * @property {String} label 表头名
 * @property {String} field 获取数据的字段
 * @property {String} wpx sheetConfig中配置，需要在外部自行处理
 */
function exportListV2(/* options */ {
    fileName,
    url,
    method = 'get',
    params = {},
    headers = {},
    limit = 100,
    total = 1000,
    columns,
    getRowsCallBack,
    totalField = 'total',
    dataField = 'list',
    sheetConfig,
    callback,
    getHeaderList,
}) {
    if (!url || !columns) {
        console.error('参数为空')
        return
    }
    // 表头信息
    var headerArr = []
    // 字段信息
    var fieldArr = []
    if (typeof getHeaderList === 'function') {
        headerArr = getHeaderList(sheetConfig)
    } else {
        columns.forEach(function (item) {
            headerArr.push(item.label)
            fieldArr.push(item.field)
        })
    }
    var loading = Ext.getBody();
    loading.mask("正在生成excel，请不要关闭页面，否则将不能导出excel")

    // 封装请求方法
    var req = function ({ url, method, params, headers }) {
        return new Promise(function (resolve, reject) {
            Ext.Ajax.request({
                url,
                method,
                params,
                headers,
                callback: function (options, success, response) {
                    var data = Ext.JSON.decode(response.responseText) || {}
                    if (!success || !data.success) {
                        return reject()
                    }
                    resolve(data)
                }
            })
        })
    }
    // 根据需要导出的次数除以每页条数，计算出步长（也就是分了多少页），需要查询几次
    // step（page）需要从0开始，方便计算 start 的值
    var steps = new Array(Math.ceil(total / limit)).fill('').map(function (_, i) {
        return i
    })
    // 获取到的数据
    var datasource = []
    // 数据库中满足条件的总数
    var totalCount = 0
    function next(index) {
        var item = JSON.parse(JSON.stringify(params))
        // 必传 start，因为后端是通过 start 计算分页的
        item.start = index * limit
        item.page = index === 0 ? 1 : index
        item.limit = limit
        req({
            url,
            method,
            params: item,
            headers
        }).then(function ({ data } = {}) {
            if (!totalCount) {
                totalCount = +data[totalField]
            }
            var record = data[dataField]
            if (Array.isArray(record)) {
                datasource = datasource.concat(record)
            }
            // 数据库中满足的条数在分页，临界点就停止请求
            if (totalCount < +limit || Math.ceil(totalCount / limit) === index) {
                make()
                return
            }
            var step = steps.shift()
            if (step) {
                next(step)
            } else {
                make()
            }
        }).catch(function (error) {
            console.error(error)
            var step = steps.shift()
            if (step) {
                next(step)
            } else {
                make()
            }
        })
    }

    next(steps.shift())

    // 处理数据
    function handler(datasource, fieldArr) {
        if (getRowsCallBack) {
            return getRowsCallBack(datasource, fieldArr)
        } else {
            return datasource.map(function (item) {
                return fieldArr.map(function (name) {
                    var value = item[name]
                    if (value === undefined || value === null) {
                        value = ''
                    }
                    return value
                })
            })
        }
    }

    function make() {
        datasource = handler(datasource, fieldArr)
        datasource.unshift(headerArr)
        // console.log(datasource)
        var sheet = XLSX.utils.aoa_to_sheet(datasource)
        if (sheetConfig) {
            for (key in sheetConfig) {
                sheet[key] = sheetConfig[key]
            }
        }
        openDownloadDialog(sheet2blob(sheet), fileName + '.xlsx')
        loading.unmask()
        if (callback) {
            callback({
                totalCount,
                total
            })
        } else {
            if (totalCount > +total) {
                //showInfo('总共可以导出 ' + totalCount + ' 条数据，可以使用查询条件筛选数据后导出');
            }
        }
    }
}